#include <stdio.h>
#include <ctype.h>

//E -> TE' 
//E' -> +TE' | e
//T -> FT'
//T' -> *FT' | e
//F -> NUM | (E)
//FIRST(E) = {NUM, LEFTB}
//FIRST(E') = {PLUS, e}
//FIRST(T) = {NUM, LEFTB}
//FIRST(T') = {MULT, e}
//FIRST(F) = {NUM, LEFTB}
//FOLLOW(E) = {$, RIGHTB}
//FOLLOW(E') = {$, RIGHTB}
//FOLLOW(T) = {PLUS, RIGHTB, $}
//FOLLOW(T') = {PLUS, RIGHTB, $}
//FOLLOW(F) = {MULT, PLUS, RIGHTB, $}

enum TOKEN {PLUS, MULT, NUM, END, ERR, LEFTB, RIGHTB};
char lookahead;
enum TOKEN token;
int num;
int error = 0;
FILE *fp;

void lexical(FILE *fp);
int match(enum TOKEN x);
int E();
int E_();
int T();
int T_();
int F();


//return 0 if success, return 1 otherwise
int match(enum TOKEN x) {
	if(token == x) {
		lexical(fp);
		return 0;
	} else {
		error = 1;
		return 1;
	}
}

//E -> TE' 
int E() {
         switch(token)
	 {
	 case NUM:
	 case LEFTB:
	   return T()+E_();
	 default:
	  error=1;
	  return 1;
	 }
	 /*if(token==NUM||token==LEFTB)
	 {
	  return T()+E_();
	 }
	 else if(token==END)
	 {
	  return 1;
	 }
	 else
	 {
	  error=1;
	  return 1;
	 }*/
}

//E_ -> +TE'|e 
int E_() {
        switch(token)
	{
	 case PLUS:
	   match(token);
	   return T()+E_();
	 case RIGHTB:
	    return 0;
	 case END:
	  return 0;
	 default:
	  error=1;
	  return 1;
	}
        /*if(token==PLUS)
	 { match(token);
	   return T()+E_();
	 }
	 else if(token==RIGHTB)
	 { 
	   match(token); 
	   return 0;
	 }
	 else if(token==END)
	 {
	  return 1;
	 }
	 else 
	 {
	  error=1;
	  return 1;
	 }*/
	
}

//T -> FT'
int T() {
        switch(token)
	{
	case NUM:
	case LEFTB:
	  return F()*T_();
        default:
	 error=1;
	 return 1;
	} 
	/*if(token==NUM||token==LEFTB)
	{
	 return F()*T_();
	}
	else if(token==END)
	{
	 return 1;
	}
	else
	{
	 error=1;
	 return 1;
	}*/
}


//T' -> *FT' | e
int T_(){       
        switch(token)
	{
	 case MULT:
	  match(token);
	  return F()*T_();
	 case PLUS:
         case RIGHTB:
	   return 1;
	 case END:
	  return 1;
	 default:
	  error=1;
	  return 1;
	}
        /*if(token==MULT)
	{ match(token);
	  return F()*T_();
	}
	else if(token==PLUS)
	{
	  match(token);
	  return 1;
	}
	else if(token==RIGHTB)
	{  match(token);
	   return 1;
        }
	else if(token==END)
	{
	 return 1;
	}
	else 
	{ error=1;
	  return 1;
	}*/
}
//F -> NUM | (E)
int F() {
        switch(token)
	{
	case NUM:
        if(!match(token))
	 {return num;}
	case LEFTB:
	  match(token);
	  int temp;
	  temp=E();
          match(token);
          return temp;
	case END:
	 return 1;
	default:
	 error=1;
	 return 1;
	}
        /*if(token==NUM)
	{ 
	  match(token);
	  return 1;
	}
        else if(token==LEFTB)
	{ match(token);
	  return E();
	}
	else if(token==END)
	{
	 return 1;
	}
	else
	{ error=1;
	  return 1;
	}*/
}
void lexical(FILE *fp) {

	lookahead = getc(fp);
	//num = 0;

	while(lookahead == ' ' || lookahead == '\t' || lookahead == '\n') {
		lookahead = getc(fp);
	}

	if(isdigit(lookahead)) {
	        num=0;
		while(isdigit(lookahead)) {
			token = NUM;
			num = num * 10 + lookahead - '0';
			lookahead = getc(fp);
		}
		ungetc(lookahead, fp);
		return;
	} else if (lookahead == '+') {
		token = PLUS;
		return;
	} else if (lookahead == '*') {
		token = MULT;
		return;
	} else if(lookahead == EOF) {
		token = END;
		return;
	}else if(lookahead == '(') {
		token = LEFTB;
		return;
	} else if(lookahead == ')') {
		token = RIGHTB;
		return;
	} else {
		error = 1;
		token = ERR;
		return;
	}
}

int main(int argc, char **argv) {
	int  res = 0;
	if(argc < 2) {
		printf("insufficient arguments");
		return 1;
	}
	fp = fopen(argv[1], "r");

	lexical(fp);
	res = E();
	if(!error) {
		printf("%d\n", res);
	} else {
		printf("There are errors\n");
	}
	
	fclose(fp);
	return 0;

}
